#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>


#define maxn 1024
char command[maxn];
char* pipe_command[maxn];
int do_face(){
    memset(command,0x00,sizeof(command));
    printf("here is : minishel\n");
    fflush(stdout);
    if(scanf("%[^\n]*c",command) == 0){
        getchar();
        exit(-1);
    }
    return 0;
}


char** do_pharse(char* buff)
{
    int argc = 0;
    static char *argv[32];
    char *ptr = buff;

    while(*ptr != '\0'){
        if(!isspace(*ptr)){
            argv[argc++] = ptr;
            while(!isspace(*ptr) && (*ptr) != '\0'){
                ptr++;
            }
        }else{
            while(isspace(*ptr)){
                *ptr = '\0';
                ptr++;
            }
        }
    }
    return argv;
}



int do_redirect(char *buff)
{
    char *ptr = buff, *file = NULL;
    int type = 0, fd, redirect_type = -1;
     while(*ptr != '\0') {
         if (*ptr == '>') {
        *ptr++ = '\0';
         redirect_type++;
        if (*ptr == '>') {
            *ptr++ = '\0';
            redirect_type++;
        }
        while(isspace(*ptr)) {
            ptr++;
        }
        file = ptr;
        while((!isspace(*ptr)) && *ptr != '\0') {
             ptr++;
        }
        *ptr = '\0';
        if (redirect_type == 0) {
            fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0664);
        }else {
            fd = open(file, O_CREAT|O_APPEND|O_WRONLY, 0664);
        }
        dup2(fd, 1);
         }
        ptr++;
     }
     return 0;
}


/*
void do_exec(char* buff){
    char** argv = {NULL};
    int pid = fork();
    if(pid == 0){
        do_redirect(buff);
        argv = do_pharse(buff);
        if(argv[0] == NULL){
            exit(-1);
        }
        execvp(argv[0], argv);
    }else{
        waitpid(pid, NULL, 0);
    }
}
*/
int do_command(char* buff){
    int pipe_num = 0, i;
    char* ptr = buff;
    int pipefd[32][2] = {{-1}};
    int pid = -1;
    pipe_command[pipe_num] = ptr;//记录第一个管道前的命令
    while(*ptr != '\0'){
        if((*ptr) == '|'){
            pipe_num ++;
            *ptr++ = '\0';
            pipe_command[pipe_num] = ptr;//记录管道后的命令
            continue;
        }
        ptr++;
    }
    pipe_command[pipe_num+1]=NULL;//标识后面没有指令了
    return pipe_num;//返回管道的个数
}

int do_pipe(int pipe_num){
    int pid = 0, i;
    int pipefd[10][2]={{0}};
    char** argv = {NULL};
    
    for(int i = 0;i <= pipe_num;i++)//如果pipe_num==0,就只相当于做do_exec的操作
    {
        pipe(pipefd[i]);//建立管道
    }

    for(int i = 0; i <= pipe_num; i++)
    {
        pid = fork();
        if(pid == 0){
            do_redirect(pipe_command[i]);
            argv = do_pharse(pipe_command[i]);
            if(i != 0){
                close(pipefd[i][1]);//关闭子进程写端
                dup2(pipefd[i][0],0);
            }
            if(i != pipe_num){
                close(pipefd[i + 1][0]);
                dup2(pipefd[i + 1][1],1);
            }
            execvp(argv[0],argv);
        }else{
            close(pipefd[i][0]);
            close(pipefd[i][1]);
            waitpid(pid, NULL, 0);
        }
    }
    return 0;
}


int main(int argc, char* argv[]){
    int num = 0;
    while(1)
    {
        if(do_face() < 0)
            continue;
        num = do_command(command);
        do_pipe(num);
    }
    return 0;
}
